// Eno.Infrastructure/Middleware/LoggingInterceptor.cs
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore;
using Eno.Application.Services;
using Microsoft.Extensions.DependencyInjection;

namespace Eno.Infrastructure.Middleware;
//! SaveChangeInterceptor拦截器
//! DbContext.SaveChanges() 或 SaveChangesAsync() 时，这个拦截器会被触发。
public class LoggingInterceptor : SaveChangesInterceptor
{
    private readonly IServiceProvider _serviceProvider;

    public LoggingInterceptor(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public override async ValueTask<int> SavedChangesAsync(
        SaveChangesCompletedEventData eventData,
        int result,
        CancellationToken cancellationToken = default)
    {
        // 在保存完成后记录日志
        await LogDatabaseChanges(eventData, result);
        return await base.SavedChangesAsync(eventData, result, cancellationToken);
    }

    private async Task LogDatabaseChanges(SaveChangesCompletedEventData eventData, int affectedRows)
    {
        if (eventData.Context == null || affectedRows == 0) return;

        using var scope = _serviceProvider.CreateScope();
        // 通过依赖注入获取日志服务
        var logService = scope.ServiceProvider.GetRequiredService<ILogService>();

        var entries = eventData.Context.ChangeTracker.Entries()
            .Where(e => e.State == EntityState.Added ||
                       e.State == EntityState.Modified ||
                       e.State == EntityState.Deleted)
            .ToList();

        foreach (var entry in entries)
        {
            var entityName = entry.Entity.GetType().Name;
            var operation = entry.State.ToString();

            var logData = new
            {
                EntityType = entityName,
                Operation = operation,
                EntityId = GetEntityId(entry),
                Changes = GetChanges(entry),
                AffectedRows = affectedRows
            };

            // 生成日志并写入数据库
            await logService.LogInfoAsync(
                $"{operation} operation on {entityName}",
                "Database Operation",
                logData
            );
        }
    }

    private object? GetEntityId(Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entry)
    {
        // 尝试获取实体的ID
        var keyProperty = entry.Properties.FirstOrDefault(p => p.Metadata.IsPrimaryKey());
        return keyProperty?.CurrentValue;
    }

    private object GetChanges(Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry entry)
    {
        return entry.State switch
        {
            EntityState.Added => entry.Properties.ToDictionary(p => p.Metadata.Name, p => p.CurrentValue),
            EntityState.Modified => entry.Properties
                .Where(p => p.IsModified)
                .ToDictionary(p => p.Metadata.Name, p => new
                {
                    Old = p.OriginalValue,
                    New = p.CurrentValue
                }),
            EntityState.Deleted => entry.Properties.ToDictionary(p => p.Metadata.Name, p => p.OriginalValue),
            _ => new { }
        };
    }
}
